﻿using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System.Collections.Generic;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using MiniX.API.Data;
using MiniX.Models;
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using Senparc.CO2NET.Extensions;
using MiniX.Utility.Helper;
using System.Security.Claims;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using MiniX.API.Filters;
using System.Text;
using MiniX.Utility.Authorization;
using Serilog.Parsing;
using Aliyun.OSS;
using Google.Protobuf;

namespace MiniX.API.Controllers
{
    /// <summary>
    /// 会员类，定义了CURD相关操作
    /// </summary>
    [Produces("application/json")]
    [Route("api/[controller]")]
    [ApiController]
    [Authorize]
    public class MembersController : BaseController<MembersController>
    {
        /// <summary>
        /// MembersController
        /// </summary>
        public MembersController(MiniXApiContext context, IHttpContextAccessor httpContextAccessor) : base(context, httpContextAccessor)
        {

        }

        /// <summary>
        /// 分页显示会员数据
        /// </summary>
        /// <param name="page">分页</param>
        /// <param name="limit">每页显示数量</param>
        /// <returns></returns>
        [HttpGet]
        [Route("/api/members")]
        public async Task<IActionResult> GetByPage(int page, int limit, int invite_member_id = -1)
        {
            try
            {
                var result = from item in _context.Set<Members>()
                             select new
                             {
                                 item.member_id,
                                 item.open_id,
                                 item.member_account,
                                 item.mobile_phone,
                                 item.member_password,
                                 item.member_name,
                                 show_member_name = CommonHelper.FormatName(item.member_account, item.member_name),
                                 item.real_name,
                                 item.gender_id,
                                 gender_name = item.gender_id > 0 ? _context.mini_genders.FirstOrDefault(t => t.gender_id == item.gender_id)!.gender_name : "-",
                                 item.member_avatar,
                                 show_member_avatar = !string.IsNullOrEmpty(item.member_avatar) ? DataFilter.GetSettingInfoValue(_context, log, (int)Utility.Helper.ENUMHelper.SettingInfoType.AliyunCallbackServer) + item.member_avatar : DataFilter.GetSettingInfoValue(_context, log, (int)Utility.Helper.ENUMHelper.SettingInfoType.ImgURL)  + "/images/no_avatar.png",
                                 item.member_birth,
                                 item.member_job,
                                 item.invite_member_id,
                                 item.invite_code,
                                 item.share_qrcode,
                                 item.source_id,
                                 source_name = item.source_id > 0 ? _context.mini_utm_sources.FirstOrDefault(t => t.source_id == item.source_id)!.source_name : "-",
                                 item.medium_id,
                                 medium_name = item.medium_id > 0 ? _context.mini_utm_mediums.FirstOrDefault(t => t.medium_id == item.medium_id)!.medium_name : "-",
                                 item.member_intro,
                                 item.member_status,
                                 item.type_id,
                                 type_name = item.type_id > 0 ? _context.mini_member_types.FirstOrDefault(t => t.type_id == item.type_id)!.type_name : "-",
                                 item.country_name,
                                 item.province_name,
                                 item.city_name,
                                 item.district_name,
                                 item.member_token,
                                 item.encrypt_token,
                                 item.member_remark,
                                 item.created_at,
                                 format_time = item.created_at.ToString("yyyy-MM-dd HH:mm")
                             };

                if (invite_member_id > 0)
                {
                    result = result.Where(t => t.invite_member_id == invite_member_id);
                }

                var list = await result.OrderByDescending(t => t.member_id).Skip((page - 1) * limit).Take(limit).ToListAsync();
                var count = result.LongCount();
                if (count <= 0)
                {
                    return Json(new { code = 0, msg = "暂无数据", count = 0 });
                }
                else
                {
                    return Json(new { code = 0, msg = "success", data = list, page = page, limit = limit, count = count, total_page = count / limit });
                }
            }
            catch (Exception ex)
            {
                log.Fatal(ex, " -> GetDataByPage");
                return Json(new { code = 1, errcode = (int)ENUMHelper.ExceptionType.List, errmsg = ex.Message });
            }
        }

        /// <summary>
        /// 根据ID获取会员详情
        /// </summary>
        /// <param name="id">会员ID</param>
        /// <returns>返回会员详情</returns>
        [HttpGet("/api/members/{id}")]
        public async Task<IActionResult> GetById(long id)
        {
            try
            {
                log.Information("id=" + id);
                var member_id = id;

                var result = await _context.mini_members.Where(t => t.member_id == id).Select(item => (new
                {
                    item.member_id,
                    item.open_id,
                    item.member_account,
                    item.mobile_phone,
                    format_phone = !string.IsNullOrEmpty(item.mobile_phone) ? Utility.Helper.CommonHelper.FormatPhone(item.mobile_phone) : "-",
                    item.member_password,
                    item.member_name,
                    item.real_name,
                    item.gender_id,
                    gender_name = item.gender_id > 0 ? _context.mini_genders.FirstOrDefault(t => t.gender_id == item.gender_id)!.gender_name : "-",
                    item.member_avatar,
                    show_member_avatar = !string.IsNullOrEmpty(item.member_avatar) ? DataFilter.GetSettingInfoValue(_context, log, (int)Utility.Helper.ENUMHelper.SettingInfoType.AliyunCallbackServer) + item.member_avatar : DataFilter.GetSettingInfoValue(_context, log, (int)Utility.Helper.ENUMHelper.SettingInfoType.ImgURL)  + "/images/no_avatar.png",
                    item.member_birth,
                    item.member_job,
                    item.invite_member_id,
                    item.invite_code,
                    item.share_qrcode,
                    item.source_id,
                    source_name = item.source_id > 0 ? _context.mini_utm_sources.FirstOrDefault(t => t.source_id == item.source_id)!.source_name : "-",
                    item.medium_id,
                    medium_name = item.medium_id > 0 ? _context.mini_utm_mediums.FirstOrDefault(t => t.medium_id == item.medium_id)!.medium_name : "-",
                    item.member_intro,
                    item.member_status,
                    item.type_id,
                    type_name = item.type_id > 0 ? _context.mini_member_types.FirstOrDefault(t => t.type_id == item.type_id)!.type_name : "-",
                    item.country_name,
                    item.province_name,
                    item.city_name,
                    item.district_name,
                    item.member_token,
                    item.encrypt_token,
                    item.member_remark,
                    item.created_at,
                    format_time = item.created_at.ToString("yyyy-MM-dd HH:mm")
                })).FirstOrDefaultAsync();
                if (result == null)
                {
                    return Json(new { code = 0, msg = "数据为空", count = 0 });
                }
                else
                {
                    // 每日登录赠送积分
                    if (!_context.mini_messages.Any(t => t.member_id == member_id && t.object_type_id == 21 && t.created_at.Date == DateTime.Now.Date))
                    {
                        var message_title = "每日登录";
                        var item_points = _context.mini_points.FirstOrDefault(t => t.point_id == 2);

                        // 添加消息
                        try
                        {
                            _context.mini_messages.Add(new Messages()
                            {
                                object_id = -1,
                                object_type_id = 21,
                                type_id = 2,
                                member_id = member_id,
                                to_member_id = -1,
                                message_title = message_title,
                                message_content = "随喜赞叹，恭喜师兄获得" + item_points!.point_num + "个积分，可到积分兑换页面进行兑换。",
                                message_img = "",
                                is_read = false,
                                message_remark = "",
                                created_at = DateTime.Now
                            });
                            _context.SaveChanges();
                        }
                        catch (Exception ex)
                        {
                            log.Fatal(ex, " -> 添加消息");
                        }

                        // 更新积分
                        try
                        {
                            var point_members = _context.mini_point_members.FirstOrDefault(t => t.member_id == member_id);
                            if (point_members != null)
                            {
                                point_members.total_point = point_members.total_point + item_points!.point_num;
                                point_members.available_point = point_members.available_point + item_points!.point_num;
                                _context.mini_point_members.Update(point_members);
                                _context.SaveChanges();
                            }
                        }
                        catch (Exception ex)
                        {
                            log.Fatal(ex, " -> 更新积分");
                        }

                        // 添加积分明细
                        try
                        {
                            _context.mini_point_records.Add(new PointRecords()
                            {
                                member_id = member_id,
                                point_id = item_points!.point_id,
                                point_num = item_points!.point_num,
                                point_action = item_points!.point_name,
                                point_token = "",
                                point_remark = "",
                                created_at = DateTime.Now
                            });
                            _context.SaveChanges();
                        }
                        catch (Exception ex)
                        {
                            log.Fatal(ex, " -> 添加积分明细");
                        }
                    }

                    return Json(new { code = 0, msg = "success", data = result });
                }
            }
            catch (Exception ex)
            {
                log.Fatal(ex, " -> Details");
                return Json(new { code = 1, errcode = (int)ENUMHelper.ExceptionType.Select, errmsg = ex.Message });
            }
        }

        /// <summary>
        /// 生成微信小程序分享二维码
        /// </summary>
        /// <param name="id">会员ID</param>
        /// <returns>返回微信小程序分享二维码</returns>
        [HttpGet("/api/members/wxqrcode")]
        public async Task<IActionResult> CreatedWXQRCode(long id)
        {
            try
            {
                log.Information("id=" + id);

                var share_qrcode = "";

                // 生成分享二维码
                try
                {
                    var item = _context.mini_members.FirstOrDefault(t => t.member_id == id);
                    if (item != null)
                    {
                        if (string.IsNullOrEmpty(item.share_qrcode))
                        {
                            // 生成路径及图片名
                            var saveDir = MiniX.API.Filters.AppSettingsFilter.GetSetting("Upload:PATH");
                            var tempPath = saveDir + "\\" + DateTime.Now.Year + "\\" + DateTime.Now.ToString("MMdd") + "\\";
                            if (!Directory.Exists(tempPath))
                            {
                                Directory.CreateDirectory(tempPath);
                            }
                            var extension = ".png";
                            var newFileName = DateTime.Now.ToString("yyyyMMddHHmmss") + MiniX.Utility.Helper.CommonHelper.GenerateRandomNum(6);
                            var savePath = tempPath + newFileName + extension;
                            var returnPath = "/" + DateTime.Now.Year + "/" + DateTime.Now.ToString("MMdd") + "/" + newFileName + extension;

                            if (!Directory.Exists(tempPath))
                            {
                                Directory.CreateDirectory(tempPath);
                            }
                            if (System.IO.File.Exists(savePath))
                            {
                                System.IO.File.Delete(savePath);
                            }

                            // 生成二维码
                            try
                            {
                                WXQRCode.GetQRCodePath("/pages/home/home?invite_member_id=" + id, savePath, 1280);
                            }
                            catch (Exception ex)
                            {
                                log.Fatal(ex, " -> 生成二维码");
                            }

                            // 更新至数据库
                            try
                            {
                                item.share_qrcode = returnPath;
                                _context.mini_members.Update(item);
                                _context.SaveChanges();
                            }
                            catch (Exception ex)
                            {
                                log.Fatal(ex, " -> 更新至数据库");
                            }

                            share_qrcode = returnPath;
                        }
                        else
                        {
                            share_qrcode = item.share_qrcode;
                        }
                    }
                }
                catch (Exception ex)
                {
                    log.Error(ex, "生成分享二维码");
                }

                var data = new
                {
                    share_qrcode = DataFilter.GetSettingInfoValue(_context, log, (int)Utility.Helper.ENUMHelper.SettingInfoType.ImgURL)  + share_qrcode,
                };

                return Json(new { code = 0, msg = "success", data = data });
            }
            catch (Exception ex)
            {
                log.Fatal(ex, " -> Details");
                return Json(new { code = 1, errcode = (int)ENUMHelper.ExceptionType.Select, errmsg = ex.Message });
            }
        }

        /// <summary>
        /// 会员登录
        /// </summary>
        /// <param name="paras">登陆参数</param>
        /// <returns></returns>
        [AllowAnonymous]
        [HttpPost("/api/members/login")]
        public async Task<IActionResult> Login(LoginParas paras)
        {
            try
            {
                // {username: "test001", password: "53344521"}
                // {mobile: "15000772515", captcha: "2222"}
                var username = paras.user_name;
                var password = paras.user_password;
                var mobile = paras.mobile;
                var captcha = paras.captcha;
                log.Information("username=" + username + ",password=" + password + ",mobile=" + mobile + ",captcha=" + captcha);

                var client_ip = Request.HttpContext.Connection.RemoteIpAddress!.MapToIPv4().ToString();

                if (!string.IsNullOrEmpty(username))
                {
                    // 用户名密码登录
                    var item = await _context.mini_members.FirstOrDefaultAsync(t => t.member_account == username);
                    if (item == null)
                    {
                        LogFilter.AddLogs(_context, log, 2, -1, ENUMHelper.ExceptionType.Login.ToString(), "用户不存在！", client_ip, "");
                        return Json(new { code = 0, msg = "用户不存在！", data = "" });
                    }
                    else
                    {
                        password = MiniX.Utility.Helper.MD5Helper.MD5Encrypt32(username + password + DateTime.Now.Year);
                        password = MiniX.Utility.Helper.MD5Helper.MD5Encrypt32(password);
                        log.Information("password=" + password + ",member_password=" + item.member_password);
                        if (item.member_password!.Contains(password.ToUpper()))
                        {
                            var token = JwtFilter.GetToken(item.member_id.ToString(), item.member_account!.ToString());

                            // 更新TOKEN
                            item.member_token = token;
                            _context.mini_members.Update(item);
                            _context.SaveChanges();

                            LogFilter.AddLogs(_context, log, 2, item.member_id, ENUMHelper.ExceptionType.Login.ToString(), "", client_ip, "");
                            return Json(new { code = 0, msg = "success", token = token, data = item });
                        }
                        else
                        {
                            LogFilter.AddLogs(_context, log, 2, item.member_id, ENUMHelper.ExceptionType.Login.ToString(), "用户名或密码错误！", client_ip, "");
                            return Json(new { code = 0, msg = "用户名或密码错误！" });
                        }
                    }
                }
                else
                {
                    // 验证码登录
                    var expires_minutes = AppSettingsFilter.GetSetting("Setting:VerifyCodeExpires");
                    var item = await _context.mini_members.FirstOrDefaultAsync(t => t.member_account!.Equals(mobile));
                    if (item == null)
                    {
                        // 手机号未注册
                        var codes = await _context.mini_codes.OrderByDescending(t => t.created_at).FirstOrDefaultAsync(t => t.mobile_phone!.Equals(mobile) && t.code_num!.Equals(captcha));
                        if (codes != null)
                        {
                            // 排除15000772515这个手机号验证码失效问题，用于苹果等各平台审核用
                            if (!mobile!.Equals("15000772515"))
                            {
                                if (codes.created_at.AddMinutes(Convert.ToInt32(expires_minutes)) < DateTime.Now)
                                {
                                    LogFilter.AddLogs(_context, log, 2, -1, ENUMHelper.ExceptionType.Login.ToString(), "验证码已失效！", client_ip, "");
                                    return Json(new { code = 0, msg = "验证码已失效！" });
                                }
                            }
                        }

                        if (!_context.mini_codes.Any(t => t.mobile_phone!.Equals(mobile) && t.code_num!.Equals(captcha)))
                        {
                            LogFilter.AddLogs(_context, log, 2, -1, ENUMHelper.ExceptionType.Login.ToString(), "验证码错误！", client_ip, "");
                            return Json(new { code = 0, msg = "验证码错误！" });
                        }

                        // 注册一个新用户
                        try
                        {
                            var members = new Members()
                            {
                                open_id = "",
                                member_account = mobile,
                                mobile_phone = mobile,
                                member_password = MiniX.Utility.Helper.MD5Helper.MD5Encrypt32(mobile),
                                member_name = mobile,
                                real_name = mobile,
                                gender_id = 3,
                                member_avatar = "",
                                member_birth = "",
                                member_job = "",
                                invite_member_id = -1,
                                invite_code = MiniX.Utility.Helper.CommonHelper.GenerateRandomNum(6),
                                share_qrcode = "",
                                source_id = 7,
                                medium_id = 1,
                                member_intro = "",
                                member_status = true,
                                type_id = 1,
                                country_name = "",
                                province_name = "",
                                city_name = "",
                                district_name = "",
                                member_token = "",
                                encrypt_token = "",
                                member_remark = "",
                                created_at = DateTime.Now
                            };
                            _context.mini_members.Add(members);
                            _context.SaveChanges();

                            var member_id = members.member_id;
                            // 新用户添加一条积分记录
                            try
                            {
                                var point = new PointMembers()
                                {
                                    member_id = member_id,
                                    total_point = 0,
                                    available_point = 0,
                                    froze_point = 0,
                                    created_at = DateTime.Now
                                };
                                _context.mini_point_members.Add(point);
                                _context.SaveChanges();
                            }
                            catch (Exception ex)
                            {
                                log.Error(ex, "新用户添加一条积分记录");
                            }

                            LogFilter.AddLogs(_context, log, 3, members.member_id, ENUMHelper.ExceptionType.Login.ToString(), "注册新会员！", client_ip, "");
                        }
                        catch (Exception ex)
                        {
                            log.Error(" -> 注册新会员", ex);
                        }

                        var item_members = _context.mini_members.FirstOrDefault(t => t.member_account!.Equals(mobile));
                        var token = "";
                        if (item_members != null)
                        {
                            token = JwtFilter.GetToken(item_members.member_id.ToString(), item_members.member_account!.ToString());

                            // 更新TOKEN
                            item_members.member_token = token;
                            _context.mini_members.Update(item_members);
                            _context.SaveChanges();
                            LogFilter.AddLogs(_context, log, 2, item_members.member_id, ENUMHelper.ExceptionType.Login.ToString(), "登录成功！", client_ip, token);
                        }

                        return Json(new { code = 0, msg = "登录成功！", token = token, data = item_members });
                    }
                    else
                    {
                        // 手机号已注册
                        var codes = await _context.mini_codes.OrderByDescending(t => t.created_at).FirstOrDefaultAsync(t => t.mobile_phone!.Equals(mobile) && t.code_num!.Equals(captcha));
                        if (codes != null)
                        {
                            if (!mobile!.Equals("15000772515"))
                            {
                                if (codes.created_at.AddMinutes(Convert.ToInt32(expires_minutes)) < DateTime.Now)
                                {
                                    LogFilter.AddLogs(_context, log, 2, -1, ENUMHelper.ExceptionType.Login.ToString(), "验证码已失效！", client_ip, "");
                                    return Json(new { code = 0, msg = "验证码已失效！" });
                                }
                            }
                        }

                        if (!_context.mini_codes.Any(t => t.mobile_phone!.Equals(mobile) && t.code_num!.Equals(captcha)))
                        {
                            LogFilter.AddLogs(_context, log, 2, -1, ENUMHelper.ExceptionType.Login.ToString(), "验证码错误！", client_ip, "");
                            return Json(new { code = 0, msg = "验证码错误！" });
                        }

                        var item_members = _context.mini_members.FirstOrDefault(t => t.member_account!.Equals(mobile));
                        var token = "";
                        if (item_members != null)
                        {
                            token = JwtFilter.GetToken(item_members.member_id.ToString(), item_members.member_account!.ToString());

                            // 更新TOKEN
                            item_members.member_token = token;
                            _context.mini_members.Update(item_members);
                            _context.SaveChanges();
                            LogFilter.AddLogs(_context, log, 2, item_members.member_id, ENUMHelper.ExceptionType.Login.ToString(), "登录成功！", client_ip, token);
                        }

                        return Json(new { code = 0, msg = "登录成功！", token = token, data = item_members });
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(" -> Login", ex);
                return Json(new { code = 1, errcode = (int)ENUMHelper.ExceptionType.Login, errmsg = ex.Message });
            }
        }

        /// <summary>
        /// 根据ID更新会员
        /// </summary>
        /// <param name="members">构造会员对象数据</param>
        /// <returns></returns>
        [HttpPost]
        [Route("/api/members/update")]
        public async Task<IActionResult> Update(Members members)
        {
            try
            {
                log.Information("members=" + members.ToJson());
                var item = _context.mini_members.FirstOrDefault(c => c.member_id == members.member_id);
                if (item != null)
                {
                    item.mobile_phone = members.mobile_phone;
                    item.member_name = members.member_name;
                    item.real_name = members.real_name;
                    item.gender_id = members.gender_id;
                    item.member_avatar = members.member_avatar;
                    item.member_birth = members.member_birth;
                    item.member_job = members.member_job;
                    item.member_intro = members.member_intro;
                    item.member_status = members.member_status;
                    item.country_name = members.country_name;
                    item.province_name = members.province_name;
                    item.city_name = members.city_name;
                    item.district_name = members.district_name;
                    _context.mini_members.Update(item);
                    await _context.SaveChangesAsync();
                }

                return Json(new { code = 0, msg = "更新成功" });
            }
            catch (Exception ex)
            {
                log.Fatal(ex, " -> Update");
                return Json(new { code = 1, errcode = (int)ENUMHelper.ExceptionType.Update, errmsg = ex.Message });
            }
        }

        /// <summary>
        /// 根据ID更新会员
        /// </summary>
        /// <param name="members">构造会员对象数据</param>
        /// <returns></returns>
        [HttpPost]
        [Route("/api/members/profile")]
        public async Task<IActionResult> Pofile(Members members)
        {
            try
            {
                log.Information("members=" + members.ToJson());
                var item = _context.mini_members.FirstOrDefault(c => c.member_id == members.member_id);
                if (item != null)
                {
                    item.member_name = members.member_name;
                    item.real_name = members.member_name;
                    item.member_avatar = members.member_avatar;
                    item.member_birth = members.member_birth;
                    item.member_job = members.member_job;
                    item.member_intro = members.member_intro;
                    _context.mini_members.Update(item);
                    await _context.SaveChangesAsync();
                }

                return Json(new { code = 0, msg = "更新成功" });
            }
            catch (Exception ex)
            {
                log.Fatal(ex, " -> Update");
                return Json(new { code = 1, errcode = (int)ENUMHelper.ExceptionType.Update, errmsg = ex.Message });
            }
        }

        /// <summary>
        /// 更新分享二维码
        /// </summary>
        /// <param name="members">构造会员对象数据</param>
        /// <returns></returns>
        [HttpPost]
        [Route("/api/members/qrcode")]
        public async Task<IActionResult> UpdateQRCode(Members members)
        {
            try
            {
                log.Information("members=" + members.ToJson());
                var item = _context.mini_members.FirstOrDefault(t => t.member_id == members.member_id);
                if (item != null)
                {
                    item.share_qrcode = members.share_qrcode;
                    _context.mini_members.Update(item);
                    await _context.SaveChangesAsync();
                }

                return Json(new { code = 0, msg = "更新成功" });
            }
            catch (Exception ex)
            {
                log.Fatal(ex, " -> Update");
                return Json(new { code = 1, errcode = (int)ENUMHelper.ExceptionType.Update, errmsg = ex.Message });
            }
        }

        /// <summary>
        /// 删除会员
        /// </summary>
        /// <param name="id">ID</param>
        /// <returns>返回是否删除成功</returns>
        [HttpPost]
        [Route("/api/members/del/{id}")]
        public async Task<IActionResult> Delete(long id)
        {
            try
            {
                log.Information("id=" + id);
                var item = _context.mini_members.Find(id);
                if (item != null)
                {
                    _context.mini_members.Remove(item);
                    await _context.SaveChangesAsync();
                }

                return Json(new { code = 0, msg = "删除成功" });
            }
            catch (Exception ex)
            {
                log.Fatal(ex, " -> Delete");
                return Json(new { code = 1, errcode = (int)ENUMHelper.ExceptionType.Delete, errmsg = ex.Message });
            }
        }

    }
}
